package impl.core;

import impl.events.uBoxChanges.UBoxClearedChange;
import impl.events.uBoxChanges.UtilityAssertionAddedChange;
import impl.events.uBoxChanges.UtilityAssertionChange;
import impl.events.uBoxChanges.UtilityAssertionRemovedChange;
import impl.util.UtilityAssertion;
import interfaces.UBoxChangeListenerInterface;
import interfaces.UBoxInterface;
import interfaces.abstracts.AbstractUBoxChange;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;

public class UBox implements UBoxInterface {

	private Collection<UtilityAssertion>			uAssertions;
	private LinkedList<UBoxChangeListenerInterface>	listeners;

	@Override
	public void clear() {
		this.uAssertions = new LinkedList<UtilityAssertion>();

		notifyListeners(new UBoxClearedChange());
	}

	@Override
	public void addUtilityAssertion(UtilityAssertion uAssertion) {
		this.uAssertions.add(uAssertion);

		notifyListeners(new UtilityAssertionAddedChange(uAssertion));
	}

	@Override
	public void removeUtilityAssertion(UtilityAssertion uAssertion) {
		this.uAssertions.remove(uAssertion);

		ArrayList<UtilityAssertion> uAssertionList = new ArrayList<UtilityAssertion>();
		uAssertionList.add(uAssertion);

		notifyListeners(new UtilityAssertionRemovedChange(uAssertionList));
	}

	@Override
	public void removeUtilityAssertions(Collection<UtilityAssertion> uAssertions) {
		this.uAssertions.removeAll(uAssertions);

		notifyListeners(new UtilityAssertionRemovedChange(uAssertions));
	}

	@Override
	public Collection<UtilityAssertion> getUtilityAssertions() {
		return this.uAssertions;
	}

	@Override
	public void addUBoxChangeListener(UBoxChangeListenerInterface l) {
		this.listeners.add(l);
	}

	@Override
	public void removeUBoxChangeListener(UBoxChangeListenerInterface l) {
		this.listeners.remove(l);
	}

	public UBox() {
		this.uAssertions = new LinkedList<UtilityAssertion>();
		this.listeners = new LinkedList<UBoxChangeListenerInterface>();
	}

	@Override
	public void editUtilityAssertion(UtilityAssertion oldUtilityAssertion, UtilityAssertion newUtilityAssertion) {
		oldUtilityAssertion.changeTo(newUtilityAssertion);
		notifyListeners(new UtilityAssertionChange());
	}

	private void notifyListeners(AbstractUBoxChange change) {
		for (UBoxChangeListenerInterface l : this.listeners) {
			l.UBoxChanged(change);
		}
	}

	public void loadUBoxFromUtilityAssertions(Collection<UtilityAssertion> utilityAssertions) {
		this.uAssertions = utilityAssertions;
	}

}
